package zzg.study.client.handler;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @Classname SlidingWindowRateLimiter
 * @Description 滑动窗口限流算法实现
 * @Date 2025/1/19 21:29
 * @Author zhuzhenguo
 */
public class SlidingWindowRateLimiter extends ChannelInboundHandlerAdapter {
    private final int limit;
    private final long windowSizeInMillis;
    private final long slotSizeInMillis;
    private final ConcurrentHashMap<Long, Integer> window;

    public SlidingWindowRateLimiter(int limit, long windowSizeInMillis, long slotSizeInMillis) {
        this.limit = limit;
        this.windowSizeInMillis = windowSizeInMillis;
        this.slotSizeInMillis = slotSizeInMillis;
        this.window = new ConcurrentHashMap<>();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        long currentTime = System.currentTimeMillis();
        long startTime = currentTime - windowSizeInMillis;
        long endTime = currentTime;
        int count = 0;
        long alignedStartTime = startTime / slotSizeInMillis * slotSizeInMillis;
        for (long time = alignedStartTime; time < endTime; time += slotSizeInMillis) {
            count += window.getOrDefault(time, 0);
        }
        if (count < limit) {
            long slot = currentTime / slotSizeInMillis * slotSizeInMillis;
            window.compute(slot, (k, v) -> (v == null)? 1 : v + 1);
            super.channelRead(ctx, msg);
        } else {
            // 拒绝请求
            ctx.close();
        }
    }
}
